﻿package fr.babos.core.data.remote 
{
	/**
	 * Les imports
	 */
	import fr.babos.core.roles.IDisposable;
	import fr.babos.core.roles.IExecutable;
	import fr.babos.core.roles.IIdentifiable;
	
	/**
	 * Cette classe permet de généraliser et de stocker chaque appel remoting de manière abstraite.
	 * Les appels peuvent être asynchrones, synchrones, de type XML / AMF ou autre.
	 * @author ZoulouX
	 */
	public class RemotingCall implements IIdentifiable, IExecutable, IDisposable
	{
		/**
		 * L'id de l'appel
		 */
		protected var _id						:uint				= 0;
		
		/**
		 * Le nom de la commande exécutée
		 */
		protected var _command					:String;
		
		/**
		 * La routine interne à exécuter
		 */
		protected var _routine					:Function;
		
		/**
		 * Les arguments de la routine
		 */
		protected var _routineArguments			:Array;
		
		/**
		 * La réponse
		 */
		protected var _response					:*;
		
		/**
		 * Les options de l'appel
		 */
		protected var _options					:Object;
		
		/**
		 * Si l'appel est en cours
		 */
		protected var _pending					:Boolean;
		
		/**
		 * S'il cet appel à été répondu (par une réussite ou une erreur)
		 */
		protected var _complete					:Boolean
		
		
		/**
		 * L'id de l'appel
		 */
		public function get id ():uint { return _id; }
		public function set id (value:uint):void
		{
			throw new Error("RemotingCall.id Error. Id can't be changed.");
		}
		
		/**
		 * Le nom de la commande
		 */
		public function get command ():String { return _command; }
		
		/**
		 * La réponse
		 */
		public function get response ():* { return _response; }
		public function set response (value:*):void 
		{
			_response = value;
		}
		
		/**
		 * La routine du call
		 */
		public function get routine ():Function { return _routine; }
		public function set routine (value:Function):void 
		{
			_routine = value;
		}
		
		/**
		 * Les arguments associés à la routine
		 */
		public function get routineArguments ():Array { return _routineArguments; }
		public function set routineArguments (value:Array):void 
		{
			_routineArguments = value;
		}
		
		/**
		 * Les options de l'appel
		 */
		public function get options ():Object { return _options; }
		public function set options (value:Object):void 
		{
			_options = value;
		}
		
		/**
		 * S'il cet appel à été répondu (par une réussite ou une erreur)
		 */
		public function get complete ():Boolean { return _complete; }
		public function set complete (value:Boolean):void 
		{
			_complete = value;
			
			if (value)
				_pending = false;
		}
		
		/**
		 * Si l'appel est en cours
		 */
		public function get pending ():Boolean { return _pending; }
		public function set pending (value:Boolean):void
		{
			_pending = value;
		}
		
		
		/**
		 * Le constructeur de l'appel.
		 * @param	pId : L'identifiant de l'appel
		 * @param	pCommand : Le nom de la commande exécutée
		 * @param	pRoutine : La routine interne à exécuter
		 * @param	pOptions : Les options de l'appel
		 */
		public function RemotingCall (pId:uint, pCommand:String, pRoutine:Function = null, pOptions:Object = null)
		{
			// Enregistrer les paramètres
			_id = pId;
			_command = pCommand;
			_routine = pRoutine;
			_options = pOptions;
		}
		
		/**
		 * Exécuter cet appel
		 */
		public function execute ():void
		{
			// L'appel est en cours
			_pending = true;
			
			// Appeler la routine en lui passant les paramètres
			_routine.apply(null, _routineArguments == null ? [] : _routineArguments);
		}
		
		/**
		 * Disposer
		 */
		public function dispose ():void
		{
			_routine = null;
			_routineArguments = null;
			_options = null;
			_response = null;
		}
	}
}